package com.xxmw.transaction.common.utils.bourse;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xxmw.transaction.common.excep.service.TransactionException;
import com.xxmw.transaction.common.utils.HmacUtil;
import com.xxmw.transaction.common.utils.SHA1Util;
import com.xxmw.transaction.common.utils.http.HttpClientUtil;
import com.xxmw.transaction.enumeration.TradeTypeEnum;
import com.xxmw.transaction.model.app.BourseApi;
import com.xxmw.transaction.model.app.BourseOrder;
import com.xxmw.transaction.model.brick.BrickOrder;
import com.xxmw.transaction.vo.BalanceVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * https://www.zb.com/api
 * 中币工具类
 * @author xiepeng
 * @since 2020-03-26
 */
@Slf4j
@Component
public class ZBUtil {

    /**
     * 下单URL
     */
    public static String ORDER_URL = "https://trade.zb.live/api/order";

    /**
     * 订单信息URL
     */
    public static String ORDER_INFO_URL = "https://trade.zb.live/api/getOrder";

    /**
     * 获取帐户信息
     */
    public  final static String USER_INFO_URL = "https://trade.zb.live/api/getAccountInfo";


    //@PostConstruct
    public void test () {
        log.info("中币测试下单-------------------------------");
        BourseApi api = new BourseApi();
        api.setAccessKey("ee099c3d-a761-4d37-816b-05b663ff282d");
        api.setSecretKey("89dc6c98-ebf8-4143-b948-1512761d1c56");
        BourseOrder order = new BourseOrder();
        order.setTradeType(TradeTypeEnum.BUY_MARKET.getValue());
        order.setSymbol("ethusdt");
        order.setNum(BigDecimal.ONE);
        order.setPrice(new BigDecimal("129"));
        order.setId(123431L);
        order(api,order);
    }

    public static void main(String[] args) {
        /*BourseApi api = new BourseApi();
        api.setAccessKey("ee099c3d-a761-4d37-816b-05b663ff282d");
        api.setSecretKey("89dc6c98-ebf8-4143-b948-1512761d1c56");
        getBalance(api, "usdt");*/
        log.info("中币测试下单-------------------------------");
        BourseApi api = new BourseApi();
        api.setAccessKey("ee099c3d-a761-4d37-816b-05b663ff282d");
        api.setSecretKey("89dc6c98-ebf8-4143-b948-1512761d1c56");
        BourseOrder order = new BourseOrder();
        order.setTradeType(TradeTypeEnum.BUY_MARKET.getValue());
        order.setSymbol("ethusdt");
        order.setNum(BigDecimal.ONE);
        order.setPrice(new BigDecimal("129"));
        order.setId(123431L);
        order(api,order);
    }


    /**
     * 下单
     * @param api
     * @param order
     */
    public static void order (BourseApi api, BourseOrder order) {

        // 交易所无市价单 手动处理
        //如果类型是市价买  金额上浮  市价卖 金额下浮
        if (order.getTradeType().equals(TradeTypeEnum.BUY_MARKET.getValue())) {
            BigDecimal price = order.getPrice().multiply(new BigDecimal("1.01"));
            order.setPrice(price);
            order.setTotalPrice(price.multiply(order.getNum()));
        } else if (order.getTradeType().equals(TradeTypeEnum.SELL_MARKET.getValue())) {
            BigDecimal price = order.getPrice().multiply(new BigDecimal("0.99"));
            order.setPrice(price);
            order.setTotalPrice(price.multiply(order.getNum()));
        }

        Map<String,Object> map =  new TreeMap();
        map.put("method","order");
        map.put("accesskey", api.getAccessKey());
        map.put("amount", order.getNum().stripTrailingZeros().toPlainString());
        map.put("currency", getSymbol(order.getSymbol()));
        map.put("price", order.getPrice().stripTrailingZeros().toPlainString());
        map.put("customerOrderId",String.valueOf(order.getId()));
        map.put("tradeType",
                order.getTradeType().equals(TradeTypeEnum.BUY_LIMIT.getValue())
                        || order.getTradeType().equals(TradeTypeEnum.BUY_MARKET.getValue())? "1" : "0");
        map.put("sign",sign(map, api));
        map.put("reqTime",String.valueOf(System.currentTimeMillis()));
        StringBuffer data = new StringBuffer();
        map.entrySet().forEach(item -> data.append(item.toString()).append("&"));
        String params = data.toString();
        params = params.substring(0, params.length()-1);
        log.info("请求的方法为：{}", ORDER_URL + "?" +params);
        String resp = HttpClientUtil.get(ORDER_URL+"?"+ params);
        log.info("中币下单接口返回数据:{}",resp);
        JSONObject object = JSONObject.parseObject(resp);
        if (object.getString("code").equals("1000")) {
            order.setStatus(BourseOrder.Status.PUBLISHED.value());
            order.setOutId(object.getString("id"));
        } else {
            log.error("中币下单失败：{}", resp);
            order.setStatus(BourseOrder.Status.PUBLISH_ERROR.value());
            order.setRemark(object.getString("message"));
        }
    }

    /**
     * 订单信息获取
     * 该接口返回信息无手续费、成交时间等
     * @param api
     * @param order
     */
    public static void orderInfo (BourseApi api, BourseOrder order) {

        Map<String,Object> paramMap =  new TreeMap();
        paramMap.put("method","getOrder");
        paramMap.put("accesskey",api.getAccessKey());
        paramMap.put("id", order.getOutId());
        paramMap.put("currency", getSymbol(order.getSymbol()));
        paramMap.put("sign", sign(paramMap, api));
        paramMap.put("reqTime",String.valueOf(System.currentTimeMillis()));

        StringBuilder sb = new StringBuilder("?");
        paramMap.entrySet().forEach(item -> sb.append(item).append("&"));

        String url = ORDER_INFO_URL + sb.toString().substring(0, sb.length() - 1);

        String res = HttpClientUtil.get(url);

        log.info("中币订单信息请求结果：{}", res);

        if (res.contains("currency")) {
            JSONObject object = JSONObject.parseObject(res);
            if (object.getInteger("status").equals(2)) {
                order.setStatus(6);
//                order.setDealTime();
                //TODO 没有手续费字段
//                order.setFee();
            }
        }
    }

    public static BalanceVo getBalance (BourseApi api, String currency) {
        JSONObject object = getBalanceObject(api);
        return getBalanceVo(object, currency);

    }

    private static BalanceVo getBalanceVo (JSONObject object, String currency) {
        JSONArray jsonArray = object.getJSONObject("result").getJSONArray("coins");
        BalanceVo balanceVo = new BalanceVo();
        if (jsonArray != null && jsonArray.size() >0) {
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject coin = jsonArray.getJSONObject(i);
                if (currency.toUpperCase().equals(coin.getString("enName"))) {
                    balanceVo.setAvailable(coin.getBigDecimal("available"));
                    balanceVo.setFrozen(coin.getBigDecimal("freez"));
                    balanceVo.setTotal(balanceVo.getAvailable().add(balanceVo.getFrozen()));
                    log.info("中币查询{}的余额为：{}", currency,balanceVo.toString());
                    return balanceVo;
                }
            }
        }
        throw new TransactionException("中币查询异常");
    }

    /**
     * 账户余额获取
     * @param api
     * @return
     */
    public static JSONObject getBalanceObject (BourseApi api) {
        //该交易所未提供接口
        Map<String,Object> paramMap =  new TreeMap();
        paramMap.put("method","getAccountInfo");
        paramMap.put("accesskey",api.getAccessKey());
        paramMap.put("sign", sign(paramMap, api));
        paramMap.put("reqTime",String.valueOf(System.currentTimeMillis()));

        StringBuilder sb = new StringBuilder("?");
        paramMap.entrySet().forEach(item -> sb.append(item).append("&"));

        String url = USER_INFO_URL + sb.toString().substring(0, sb.length() - 1);
        log.info("请求url:{}", url);
        String res = HttpClientUtil.get(url);

        log.info("中币请求用户信息请求结果：{}", res);
        return JSONObject.parseObject(res);
    }

    public static Map<String, BalanceVo> getBalance (BourseApi api, List<String> currency) {
        Map<String, BalanceVo> map = new HashMap<>(16);
        if (currency.size() <= 0) {
            return map;
        }
        JSONObject object = getBalanceObject(api);
        for (String s : currency) {
            map.put(s,  getBalanceVo(object, s));
        }
        return map;
    }

    public static String getSymbol(String symbol){
        String res = null;
        switch (symbol) {
            case "btcusdt":
                res = "btc_usdt";
                break;
            case "ethusdt":
                res = "eth_usdt";
                break;
            case "btc_usdt":
                res = "btcusdt";
                break;
            case "eth_usdt":
                res = "ethusdt";
                break;
        }
        return res;
    }

    /**
     * 获取签名
     * @param map
     * @param api
     * @return
     */
    private static String sign (Map<String, Object> map, BourseApi api) {
        StringBuffer data = new StringBuffer();
        map.entrySet().forEach(item -> data.append(item.toString()).append("&"));
        String params = data.toString();
        params = params.substring(0, params.length()-1);
        try {
            String secretKey = SHA1Util.shaEncode(api.getSecretKey());
            String res = HmacUtil.ZBSign(params, secretKey);
            return res;
        } catch (Exception e) {
        }
        return null;
    }




}
